#ifndef __FDT_NET_H__
#define __FDT_NET_H__
/*******************************************************************************
 * @file fdt_net.h
 * @brief  
 *
 *
 * Author: Kevinx
 *
 * Copyright (c) 2016 Kevinx. All Rights Reserved.
 *
 * CONFIDENTIALITY AND LIMITED USE
 *
 * This software, including any software of third parties embodied herein,
 * contains information and concepts which are confidential to Kevinx
 * and such third parties. This software is licensed for use
 * solely in accordance with the terms and conditions of the applicable
 * license agreement with Kevinx or its authorized distributor.
 ************************************************************************************/
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h> 
#include <fcntl.h>
#include <time.h>  
#include <sys/socket.h>  
#include <sys/types.h>  
#include <netinet/in.h>  
#include <errno.h>
#include "cyclic_list.h"

struct fdt_socket;
struct fdt_sock_ops 
{
    int (*open)(struct fdt_socket*, int);
    void (*close)(struct fdt_socket*);    
    int (*connect)(struct fdt_socket*, struct sockaddr*, socklen_t);
    int (*bind)(struct fdt_socket*, struct sockaddr*, socklen_t addrlen);
    int (*listen)(struct fdt_socket*);
    struct fdt_socket* (*accept)(struct fdt_socket*, struct sockaddr*, socklen_t *addrlen);
    ssize_t (*recvive)(struct fdt_socket*, void*, size_t);
    ssize_t (*send)(struct fdt_socket*, const void*, size_t);
    int (*poll)(struct fdt_socket*, struct timeval*);
};

struct fdt_sock_cb {
    int (*func)(struct fdt_socket*);
};

struct fdt_socket {
    int fd;    
    struct fdt_sock_ops* ops;
    struct fdt_sock_cb* cb;
    struct list_head list;
    struct sockaddr addr;
    socklen_t addrlen;
};

void make_tcp_srv_socket(struct fdt_socket* sock);

void make_tcp_socket(struct fdt_socket* sock);

void make_udp_socket(struct fdt_socket* sock, struct sockaddr* daddr, socklen_t addrlen);

static inline int fdt_sock_open(struct fdt_socket* sock, int flags)
{
    if (sock->ops->open(sock, flags) == -1)
        return -1;

    return 0;
}

static inline void fdt_sock_close(struct fdt_socket* sock)
{
    if (likely(sock))
        sock->ops->close(sock);
}

static inline int fdt_sock_bind(struct fdt_socket* sock, struct sockaddr* saddr, socklen_t addrlen)
{
    if (likely(sock))
        return sock->ops->bind(sock, saddr, addrlen);

    return -1;
}

static inline int fdt_sock_listen(struct fdt_socket* sock)
{
     return sock->ops->listen(sock);
}

static inline struct fdt_socket* fdt_sock_accept(struct fdt_socket* sock, struct sockaddr* addr, socklen_t *addrlen)
{
    return sock->ops->accept(sock, addr, addrlen);
}

static inline int fdt_sock_connect(struct fdt_socket* sock, struct sockaddr* addr, socklen_t len)
{
    return sock->ops->connect(sock, addr, len);
}

static inline int fdt_sock_send_msg(struct fdt_socket* sock,  const char* buf, ssize_t len)
{
    return sock->ops->send(sock, buf, len);
}

static inline int fdt_sock_recv_msg(struct fdt_socket* sock, char* buf, ssize_t len)
{
    return sock->ops->recvive(sock, buf, len);
}

static inline int fdt_sock_poll(struct fdt_socket* sock, struct timeval* tv)
{
     return sock->ops->poll(sock, tv);
}

#endif /* __FDT_NET_H__ */
